package me.buick.util.snmp.core.dao.impl.snmp;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import me.buick.util.snmp.core.SupportedOS;
import me.buick.util.snmp.core.dao.DiskInfoDAO;
import me.buick.util.snmp.core.pojo.DiskIOPojo;
import me.buick.util.snmp.core.pojo.DiskUsagePojo;

import org.opengoss.snmphibernate.api.ISnmpSession;

/**
 * 
 * Version 1.0
 * 
 * @author buick
 *
 */

public class SNMPDiskInfoDAO implements DiskInfoDAO, IPollable{

	ISnmpSession session = null;
	SupportedOS  os	     = SupportedOS.Linux;
	
	Map<String, DiskUsagePojo> diskUsagePojoMap;
	Map<String, DiskIOPojo>    beforediskIOPojoMap;
	Map<String, DiskIOPojo>    finalIOPojoMap;
	long					   lastPolled;
	
	public SNMPDiskInfoDAO(SupportedOS os, ISnmpSession session){
		this.session = session;
		this.os		 = os;
	}
	
	public Map<String, DiskUsagePojo> getDiskUsageInfo(){
		return this.getDiskUsagePojo();
	}
	
	public Map<String,DiskIOPojo> getDiskIOInfo(){
		if(this.finalIOPojoMap != null){
			return this.finalIOPojoMap;
		}
		return extractDiskIOInfo();

	}

	private Map<String, DiskIOPojo> extractDiskIOInfo() {
		if(this.os == SupportedOS.Windows){
			List<me.buick.util.snmp.core.dao.impl.snmp.os.windows.entity.HrDiskUsageEntry> diskUsageResultList = null;
			try {
				diskUsageResultList = session.getTable(me.buick.util.snmp.core.dao.impl.snmp.os.windows.entity.HrDiskUsageEntry.class);
			} catch (Exception e1) {
				e1.printStackTrace();
			} 
			if(diskUsageResultList == null){
				return null;
			}
			try {
				List<me.buick.util.snmp.core.dao.impl.snmp.os.windows.entity.HrDiskIOEntry> ioEntries = session.getTable(me.buick.util.snmp.core.dao.impl.snmp.os.windows.entity.HrDiskIOEntry.class);
				Map<String,DiskIOPojo> diskPartitionsIO = new HashMap<String, DiskIOPojo>();
				List<String> partionsNameList = new ArrayList<String>();
				for(me.buick.util.snmp.core.dao.impl.snmp.os.windows.entity.HrDiskUsageEntry du : diskUsageResultList){
					if(du.getHrStorageType() != null && (du.getHrStorageType().equalsIgnoreCase("1.3.6.1.2.1.25.2.1.4"))){
						partionsNameList.add(du.getHrStorageDescr().substring(0,du.getHrStorageDescr().indexOf("\\")).toLowerCase());
					}
				}
				for(me.buick.util.snmp.core.dao.impl.snmp.os.windows.entity.HrDiskIOEntry dio : ioEntries){
					if(partionsNameList.contains(dio.getDiskIOInstance().toLowerCase())){
						DiskIOPojo pojo = new DiskIOPojo();
						pojo.setDiskIOInstance(dio.getDiskIOInstance());
						pojo.setDiskIONReadsPS(dio.getDiskReadsPS());
						pojo.setDiskIOReadBytesPS(dio.getDiskReadBytesPS());
						pojo.setDiskIONWritesPS(dio.getDiskWritesPS());
						pojo.setDiskIOWriteBytesPS(dio.getDiskWriteBytesPS());
						diskPartitionsIO.put(dio.getDiskIOInstance().toLowerCase(), pojo);
					}
				}
				return diskPartitionsIO;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}else if(this.os == SupportedOS.Linux){
			List<me.buick.util.snmp.core.dao.impl.snmp.os.linux.entity.HrDiskIOEntry> diskIOResultList 		= null;
			List<me.buick.util.snmp.core.dao.impl.snmp.os.linux.entity.HrPartitionEntry> partitionResultList = null;
			try{
				diskIOResultList = session.getTable(me.buick.util.snmp.core.dao.impl.snmp.os.linux.entity.HrDiskIOEntry.class);
				partitionResultList = session.getTable(me.buick.util.snmp.core.dao.impl.snmp.os.linux.entity.HrPartitionEntry.class);
			}catch(Exception e){
				e.printStackTrace();
			}
			Map<String,DiskIOPojo> diskPartitionsIO = new HashMap<String, DiskIOPojo>();
			List<String> partionsNameList = new ArrayList<String>();
			if(partitionResultList !=null && partitionResultList.size() > 0){
				for(me.buick.util.snmp.core.dao.impl.snmp.os.linux.entity.HrPartitionEntry hrp : partitionResultList){
					partionsNameList.add(hrp.getHrPartitionLabel().substring(hrp.getHrPartitionLabel().lastIndexOf("/")+1).toLowerCase());
				}
			}
			for(me.buick.util.snmp.core.dao.impl.snmp.os.linux.entity.HrDiskIOEntry dio : diskIOResultList){
				if(partionsNameList.size() > 0){
					if(partionsNameList.contains(dio.getDiskIODeviceName().toLowerCase())){
						DiskIOPojo pojo = new DiskIOPojo();
						pojo.setDiskIndex(dio.getDiskIOIndex());
						pojo.setDiskIONReads(dio.getDiskIONmberOfReads());
						pojo.setDiskIONWrites(dio.getDiskIONumberOfWrites());
						pojo.setDiskIOReadBytes(dio.getDiskIOReadBytes());
						pojo.setDiskIOWrittenBytes(dio.getDiskIOWrittenBytes());
						diskPartitionsIO.put(dio.getDiskIODeviceName().toLowerCase(), pojo);
					}
				}else{
					if(dio.getDiskIODeviceName().toLowerCase().contains("sd") && dio.getDiskIODeviceName().toLowerCase().length() > 3){
						DiskIOPojo pojo = new DiskIOPojo();
						pojo.setDiskIndex(dio.getDiskIOIndex());
						pojo.setDiskIONReads(dio.getDiskIONmberOfReads());
						pojo.setDiskIONWrites(dio.getDiskIONumberOfWrites());
						pojo.setDiskIOReadBytes(dio.getDiskIOReadBytes());
						pojo.setDiskIOWrittenBytes(dio.getDiskIOWrittenBytes());
						diskPartitionsIO.put(dio.getDiskIODeviceName().toLowerCase(), pojo);
					}
				}
			}
			return diskPartitionsIO;
		}
		return null;
	}
	
	private Map<String, DiskUsagePojo> getDiskUsagePojo(){
		if(this.diskUsagePojoMap != null){
			return diskUsagePojoMap;
		}
		return extractDiskUsageInfo();
	}

	private Map<String, DiskUsagePojo> extractDiskUsageInfo() {
		if(this.os == SupportedOS.Windows){
			List<me.buick.util.snmp.core.dao.impl.snmp.os.windows.entity.HrDiskUsageEntry> diskUsageResultList = null;
			try {
				diskUsageResultList = session.getTable(me.buick.util.snmp.core.dao.impl.snmp.os.windows.entity.HrDiskUsageEntry.class);
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			Map<String, DiskUsagePojo> tempDiskUsage = new HashMap<String, DiskUsagePojo>();
			for(me.buick.util.snmp.core.dao.impl.snmp.os.windows.entity.HrDiskUsageEntry d : diskUsageResultList){
				if(d.getHrStorageType() != null && (d.getHrStorageType().equalsIgnoreCase("1.3.6.1.2.1.25.2.1.4"))){
					DiskUsagePojo pojo = new DiskUsagePojo();
					pojo.setPartitionName(d.getHrStorageDescr().substring(0,d.getHrStorageDescr().indexOf("\\")));
					long partitionSize = d.getHrStorageSize()*(d.getHrAllocationUnits());
					long partitionUsed = d.getHrStorageUsed()*(d.getHrAllocationUnits());
					pojo.setPartitionSizeBytes(partitionSize);
					pojo.setPartitionUsedBytes(partitionUsed);
					tempDiskUsage.put(pojo.getPartitionName(), pojo);
				}else{
				   continue;
				}
			}
			return tempDiskUsage;
		}else if(this.os == SupportedOS.Linux){
			List<me.buick.util.snmp.core.dao.impl.snmp.os.linux.entity.HrDiskUsageEntry> diskUsageResultList = null;
			try{
				diskUsageResultList = session.getTable(me.buick.util.snmp.core.dao.impl.snmp.os.linux.entity.HrDiskUsageEntry.class);
			}catch(Exception e){
				e.printStackTrace();
			}
			Map<String, DiskUsagePojo> tempDiskUsage = new HashMap<String, DiskUsagePojo>();
			for(me.buick.util.snmp.core.dao.impl.snmp.os.linux.entity.HrDiskUsageEntry d : diskUsageResultList){
				if(d.getHrStorageDescr() != null && (!d.getHrStorageDescr().toLowerCase().contains("swap"))&&(!d.getHrStorageDescr().toLowerCase().contains("memory"))){
					DiskUsagePojo pojo = new DiskUsagePojo();
					pojo.setPartitionName(d.getHrStorageDescr());
					long partitionSize = d.getHrStorageSize()*(d.getHrAllocationUnits());
					long partitionUsed = d.getHrStorageUsed()*(d.getHrAllocationUnits());
					pojo.setPartitionSizeBytes(partitionSize);
					pojo.setPartitionUsedBytes(partitionUsed);
					tempDiskUsage.put(d.getHrStorageDescr(), pojo);
				}else{
				   continue;
				}
			}
			return tempDiskUsage;
		}else{
			return null;
		}
	}

	public void poll(long interval) {
		if(this.os == SupportedOS.Windows){
			this.finalIOPojoMap   = extractDiskIOInfo();
			this.diskUsagePojoMap = this.getDiskUsageInfo();
		}else if(this.os == SupportedOS.Linux){
			if(this.beforediskIOPojoMap == null){
				this.lastPolled = System.currentTimeMillis();
				beforediskIOPojoMap = this.extractDiskIOInfo();
				this.diskUsagePojoMap = this.getDiskUsageInfo();
			}else{
				this.diskUsagePojoMap = this.getDiskUsageInfo();
				Map<String, DiskIOPojo> diskPartitionsIO = new HashMap<String, DiskIOPojo>();
				Map<String, DiskIOPojo> preIO = this.beforediskIOPojoMap;
				Map<String, DiskIOPojo> postIO = this.extractDiskIOInfo();
				long now  = System.currentTimeMillis();
				long diff = now - this.lastPolled;
				if(diff <= 0){
					diff = 1;
				}
				this.lastPolled = now;
				Set<String> pnSet = postIO.keySet();
				for (String pn : pnSet) {
					DiskIOPojo prej = preIO.get(pn);
					DiskIOPojo postj = postIO.get(pn);
					if (prej != null) {
						DiskIOPojo pojoIO = new DiskIOPojo();
						pojoIO.setDiskIndex(postj.getDiskIndex());
						pojoIO.setDiskIONReadsPS((long)(((postj.getDiskIONReads()
								- prej.getDiskIONReads())/(((double)diff)))*1000));
						pojoIO.setDiskIONWritesPS((long)(((postj.getDiskIONWrites()
								- prej.getDiskIONWrites())/(((double)diff)))*1000));
						pojoIO.setDiskIOReadBytesPS((long)(((postj.getDiskIOReadBytes()
								- prej.getDiskIOReadBytes())/(((double)diff)))*1000));
						pojoIO.setDiskIOWriteBytesPS((long)(((postj.getDiskIOWrittenBytes()
								- prej.getDiskIOWrittenBytes())/(((double)diff)))*1000));
						diskPartitionsIO.put(pn, pojoIO);
					} else {
						continue;
					}
				}
				this.finalIOPojoMap = diskPartitionsIO;
				this.beforediskIOPojoMap = postIO;
			}
		}
	}
	
}
